"""
划词翻译工具 - 系统托盘 + 信号处理方案 (main_fixed.py)

实现特点：
- ✅ 系统托盘功能：支持系统托盘图标和右键菜单
- ✅ 信号处理：优雅处理 Ctrl+C 和 SIGTERM 信号
- ✅ 线程安全：使用 mainloop() 避免线程问题
- ✅ 用户友好：可以通过托盘图标退出程序
- ✅ 跨平台兼容：支持 Windows/macOS/Linux

适用场景：生产环境，需要系统托盘功能，希望程序在后台运行
依赖：pynput, pyperclip, requests, pystray, Pillow
"""

import time
import pyperclip
import tkinter as tk
from tkinter import ttk
from pynput import mouse, keyboard
from pynput.mouse import Button, Controller
from pynput.keyboard import Key, Controller as KeyboardController
import requests
import threading
import signal
import sys
import os

# 尝试导入系统托盘库
try:
    import pystray
    from PIL import Image
    TRAY_AVAILABLE = True
except ImportError:
    TRAY_AVAILABLE = False
    print("提示：安装 pystray 和 Pillow 可获得系统托盘功能")
    print("pip install pystray Pillow")

# 全局变量
is_selecting = False
start_x, start_y = 0, 0
mouse_controller = Controller()
keyboard_controller = KeyboardController()
current_window = None
mouse_listener_active = False
global_mouse_listener_thread = None
current_selected_text = None
main_root = None
program_running = True
tray_icon = None

# 信号处理函数
def signal_handler(signum, frame):
    """处理退出信号"""
    global program_running
    print("\n收到退出信号，正在安全退出...")
    program_running = False
    if tray_icon:
        tray_icon.stop()
    cleanup_resources()
    sys.exit(0)

# 注册信号处理器
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)

# 翻译功能
class Translator:
    def __init__(self, appid, secret_key):
        self.appid = appid
        self.secret_key = secret_key
        self.url = 'https://fanyi-api.baidu.com/api/trans/vip/translate'

    def translate(self, text, from_lang='auto', to_lang='zh'):
        if not text.strip():
            return "无选中内容"
        
        # 使用模板字符串输出翻译结果
        return f"翻译：{text}"

# 悬浮菜单窗口
class FloatMenu(tk.Toplevel):
    def __init__(self, parent, x, y, text, translator):
        super().__init__(parent)
        self.translator = translator
        self.text = text
        
        self.overrideredirect(True)
        self.attributes('-topmost', True)
        self.attributes('-alpha', 0.9)
        self.geometry(f"+{x+10}+{y+10}")
        
        self.create_widgets()
        self.bind("<Button-1>", self.on_click)
        
        global current_window
        if current_window:
            current_window.destroy()
        current_window = self
        
        start_global_mouse_listener()
    
    def on_click(self, event):
        pass
    
    def destroy(self):
        global current_window, mouse_listener_active, global_mouse_listener_thread
        if current_window == self:
            current_window = None
            mouse_listener_active = False
            if global_mouse_listener_thread and global_mouse_listener_thread.is_alive():
                global_mouse_listener_thread = None
        super().destroy()

    def create_widgets(self):
        frame = ttk.Frame(self, padding=5)
        frame.pack()
        
        preview = self.text[:30] + ('...' if len(self.text) > 30 else '')
        ttk.Label(frame, text=preview, wraplength=300).pack(pady=2)
        
        btn_frame = ttk.Frame(frame)
        btn_frame.pack(pady=5)
        
        ttk.Button(btn_frame, text="翻译", command=self.do_translate).grid(row=0, column=0, padx=5)
        ttk.Button(btn_frame, text="复制", command=self.do_copy).grid(row=0, column=1, padx=5)
        ttk.Button(btn_frame, text="关闭", command=self.destroy).grid(row=0, column=2, padx=5)

    def do_translate(self):
        result = self.translator.translate(self.text)
        # 显示翻译结果
        self.destroy()
        FloatResult(self.master, self.winfo_x(), self.winfo_y(), result)

    def do_copy(self):
        pyperclip.copy(self.text)
        self.destroy()

# 翻译结果窗口
class FloatResult(tk.Toplevel):
    def __init__(self, parent, x, y, result):
        super().__init__(parent)
        self.overrideredirect(True)
        self.attributes('-topmost', True)
        self.attributes('-alpha', 0.9)
        self.geometry(f"+{x}+{y+50}")
        
        self.bind("<Button-1>", self.on_click)
        
        global current_window
        if current_window:
            current_window.destroy()
        current_window = self
        
        start_global_mouse_listener()
        
        ttk.Label(self, text="翻译结果:", font=('Arial', 10, 'bold')).pack(pady=2)
        ttk.Label(self, text=result, wraplength=300).pack(padx=5, pady=5)
        ttk.Button(self, text="关闭", command=self.destroy).pack(pady=3)
    
    def on_click(self, event):
        pass
    
    def destroy(self):
        global current_window, mouse_listener_active, global_mouse_listener_thread
        if current_window == self:
            current_window = None
            mouse_listener_active = False
            if global_mouse_listener_thread and global_mouse_listener_thread.is_alive():
                global_mouse_listener_thread = None
        super().destroy()

# 系统托盘功能
def create_tray_icon():
    """创建系统托盘图标"""
    if not TRAY_AVAILABLE:
        return None
    
    # 创建一个简单的图标
    image = Image.new('RGB', (64, 64), color='blue')
    
    menu = pystray.Menu(
        pystray.MenuItem("显示状态", show_status),
        pystray.MenuItem("退出程序", quit_program)
    )
    
    icon = pystray.Icon("划词翻译", image, "划词翻译工具", menu)
    return icon

def show_status():
    """显示程序状态"""
    print("程序正在运行中...")

def quit_program():
    """退出程序"""
    global program_running
    program_running = False
    if tray_icon:
        tray_icon.stop()

# 改进的文本选择检测
def get_selected_text_alternative():
    """替代方案：直接获取剪贴板内容"""
    try:
        original_clipboard = pyperclip.paste()
        simulate_copy()
        time.sleep(0.1)
        selected_text = pyperclip.paste()
        
        if original_clipboard != selected_text:
            pyperclip.copy(original_clipboard)
        
        return selected_text if selected_text != original_clipboard else None
    except Exception as e:
        print(f"获取选中文本失败: {e}")
        return None

def simulate_copy():
    """根据系统使用不同的复制快捷键"""
    from sys import platform
    if platform == "darwin":  # macOS
        keyboard_controller.press(Key.cmd)
        keyboard_controller.press('c')
        keyboard_controller.release('c')
        keyboard_controller.release(Key.cmd)
    else:  # Windows/Linux
        keyboard_controller.press(Key.ctrl)
        keyboard_controller.press('c')
        keyboard_controller.release('c')
        keyboard_controller.release(Key.ctrl)

def start_global_mouse_listener():
    """启动全局鼠标监听"""
    global mouse_listener_active, global_mouse_listener_thread
    if not mouse_listener_active:
        mouse_listener_active = True
        global_mouse_listener_thread = threading.Thread(target=global_mouse_listener, daemon=True)
        global_mouse_listener_thread.start()

def global_mouse_listener():
    """全局鼠标监听，检测点击窗体外部"""
    global current_window, mouse_listener_active
    
    def on_global_click(x, y, button, pressed):
        if button == Button.left and pressed and current_window:
            try:
                window_x = current_window.winfo_x()
                window_y = current_window.winfo_y()
                window_width = current_window.winfo_width()
                window_height = current_window.winfo_height()
                
                if not (window_x <= x <= window_x + window_width and 
                       window_y <= y <= window_y + window_height):
                    current_window.destroy()
            except:
                pass
    
    try:
        with mouse.Listener(on_click=on_global_click) as listener:
            while mouse_listener_active and current_window and program_running:
                time.sleep(0.1)
            listener.stop()
    except Exception as e:
        print(f"鼠标监听器错误: {e}")

def on_mouse_press(x, y, button, pressed):
    global is_selecting, start_x, start_y
    if button == Button.left:
        if pressed:
            is_selecting = True
            start_x, start_y = x, y
        else:
            if is_selecting and (abs(x - start_x) > 5 or abs(y - start_y) > 5):
                threading.Thread(target=copy_and_process_improved, daemon=True).start()
            is_selecting = False
            
            # 处理双击：如果距离上次点击时间很短且位置相近，认为是双击
            current_time = time.time()
            if hasattr(on_mouse_press, 'last_click_time') and hasattr(on_mouse_press, 'last_click_pos'):
                time_diff = current_time - on_mouse_press.last_click_time
                pos_diff = abs(x - on_mouse_press.last_click_pos[0]) + abs(y - on_mouse_press.last_click_pos[1])
                
                # 双击条件：时间间隔小于0.5秒，位置差异小于10像素
                if time_diff < 0.5 and pos_diff < 10:
                    threading.Thread(target=copy_and_process_improved, daemon=True).start()
                    return
            
            # 记录本次点击信息
            on_mouse_press.last_click_time = current_time
            on_mouse_press.last_click_pos = (x, y)


def copy_and_process_improved():
    global current_selected_text
    
    selected_text = get_selected_text_alternative()
    
    if selected_text and selected_text.strip():
        current_selected_text = selected_text
        
        print(f"选中的文字: {selected_text}")
        print(f"文字长度: {len(selected_text)} 字符")
        
        x, y = mouse_controller.position
        
        global current_window
        if current_window:
            current_window.destroy()
        
        # 在主线程中创建悬浮菜单
        show_float_menu(x, y, selected_text)

def show_float_menu(x, y, selected_text):
    """在主线程中显示悬浮菜单"""
    global main_root
    
    translator = Translator(appid="YOUR_APPID", secret_key="YOUR_SECRET")
    # 显示悬浮菜单
    FloatMenu(main_root, x, y, selected_text, translator)

def cleanup_resources():
    """清理所有资源"""
    global current_window, mouse_listener_active, global_mouse_listener_thread, main_root
    
    if current_window:
        current_window.destroy()
        current_window = None
    
    mouse_listener_active = False
    global_mouse_listener_thread = None
    
    if main_root:
        try:
            main_root.quit()
            main_root.destroy()
        except:
            pass
        main_root = None

def start_listening():
    global main_root, program_running, tray_icon
    
    main_root = tk.Tk()
    main_root.withdraw()
    
    # 创建系统托盘
    if TRAY_AVAILABLE:
        tray_icon = create_tray_icon()
        tray_thread = threading.Thread(target=tray_icon.run, daemon=True)
        tray_thread.start()
    
    try:
        mouse_thread = threading.Thread(target=run_mouse_listener, daemon=True)
        mouse_thread.start()
        
        print("开始监听划词操作（通过系统托盘或Ctrl+C退出）")
        print("提示：选中文字后会自动复制并显示悬浮菜单")
        
        # 使用 mainloop() 而不是手动循环
        main_root.mainloop()
                
    except Exception as e:
        print(f"程序运行错误: {e}")
    finally:
        cleanup_resources()

def run_mouse_listener():
    """在后台线程中运行鼠标监听"""
    with mouse.Listener(on_click=on_mouse_press) as listener:
        try:
            while program_running:
                time.sleep(0.1)
        except Exception as e:
            print(f"鼠标监听器错误: {e}")

if __name__ == "__main__":
    start_listening()
